﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Medianamik.Core.Configuration;
using Medianamik.UI;
using Medianamik.Core.Sugar;
using Medianamik.Core;
using Medianamik.Core.Security;
using Medianamik.UI.Controls;
using Telerik.Web.UI;

namespace Medianamik.UI.ContentManagement
{
    public partial class SecurityManagement : BasePage
    {
        #region Fields

        private Guid _nodeID;  // Param obligatoire

        protected readonly BaseModalWindow GroupSelectorWindow = new BaseModalWindow { ID = "GroupSelectorWindow" };

        #endregion

        #region Events

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            InitGroupSelectorWindow();

            GroupGrid.ItemCommand += OnApprobationItemCommand;
            DefaultGroups.Click += DefaultGroupsClick;

            if(SecurityManager.ApprobationEnabled)
            {
                tabApprobation.Visible = true;
                Approbation.Visible = true;
            }
        }

        protected void DefaultGroupsClick(object sender, EventArgs e)
        {
            SecurityManager.RemoveApprobationFromNode(CurrentNode);
            InitGrid();
            GroupGrid.DataBind();
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            // Param obligatoire
            if (!StringHelper.IsGuid(Request.QueryString[DefaultParamNames.NodeID], out _nodeID) || CurrentNode == null)
            {
                Response.Redirect(ReturnURL);
            }

            if (!IsPostBack)
            {
                if (!Roles.IsUserInRole("ManageSecurity") ||
                    !Roles.UserHasRight(CurrentNode, SecurityLevels.Grant))
                    Response.Redirect("/medianamik/Unauthorized.aspx");

                LoadPermissions();
                LoadBreadcrumbs();
            }
        }

        // Delete
        protected void OnApprobationItemCommand(object source, GridCommandEventArgs e)
        {
            if(e.CommandName == "DeleteGroup")
            {
                GroupItems.RemoveAll(x => x.Id == new Guid((string)e.CommandArgument));
                GroupItems = GroupItems;
                DataBindGroupItems();
            }
        }

        protected void SavePermissionsAndApprobations(object sender, EventArgs e)
        {
            SecurityManager.ApplyPermissionsToNode(CurrentNode, nodePermissionSelector.Permissions);
            if (SecurityManager.ApprobationEnabled)
            {
                SecurityManager.ApplyApprobationToNode(CurrentNode, new Approbation(CurrentNode.ID, GroupItems.OrderBy(x => x.Index).Select(x => x.Id)));
            }
            

            Response.Redirect(ReturnURL);
        }

        protected void DataBindGroupItems(object source, GridNeedDataSourceEventArgs e)
        {
            InitGrid();
        }

        protected void AddApprobationItem(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(SelectedGroupNodeId.Value))
            {
                GroupItems.Add(new GroupItem(new Guid(SelectedGroupNodeId.Value), SelectedGroupName.Value, GroupItems.Count + 1));
                GroupItems = GroupItems;
                DataBindGroupItems();
            }
        }

        protected void OnApprobationItemRowDrop(object sender, GridDragDropEventArgs e)
        {
            if (e.DraggedItems.Count > 0 && e.DestDataItem != null)
            {
                int sourceIndex = e.DraggedItems[0].ItemIndex;
                int destIndex = e.DestDataItem.ItemIndex;

                var tmp = GroupItems[sourceIndex];
                GroupItems.RemoveAt(sourceIndex);

                GroupItems.Insert(destIndex, tmp);

                GroupItems = GroupItems;
                DataBindGroupItems();
            }
        }

        #endregion

        #region Properties

        private Node _currentNode;
        public Node CurrentNode
        {
            get
            {
                if (_currentNode == null)
                {
                    _currentNode = NodeManager.GetNode(_nodeID);
                }

                return _currentNode;
            }
        }

        private string _returnURL = null;
        public string ReturnURL
        {
            get
            {
                if (_returnURL == null)
                {
                    _returnURL = "nodelist.aspx";

                    if (CurrentNode != null && CurrentNode.ParentID.HasValue)
                    {
                        _returnURL += "?" + DefaultParamNames.ParentNodeID + "=" + CurrentNode.ParentID.ToString();
                    }
                }

                return _returnURL;
            }
        }

        protected bool ApprobationIsOwned
        {
            get
            {
                if (CurrentNode.Approbation == null)
                    return false;

                return !CurrentNode.Approbation.GetGroups().Select(x => x.ID).SequenceEqual(GroupItems.Select(x => x.Id)) || CurrentNode.Approbation.IsOwned;
            }
        }

        protected List<GroupItem> GroupItems
        {
            get
            {
                if (ViewState["Medianamik.UI.ContentManagement.SecurityManagement.GroupItems"] == null)
                    ViewState["Medianamik.UI.ContentManagement.SecurityManagement.GroupItems"] = new List<GroupItem>();
                return (List<GroupItem>)ViewState["Medianamik.UI.ContentManagement.SecurityManagement.GroupItems"];
            }
            set { ViewState["Medianamik.UI.ContentManagement.SecurityManagement.GroupItems"] = value; }
        }

        #endregion

        #region Methods

        private void LoadPermissions()
        {
            nodePermissionSelector.SecuredObjectId = _nodeID;
            nodePermissionSelector.DataBind();
        }

        private void LoadBreadcrumbs()
        {
            if (CurrentNode != null)
            {
                bctFilAriane.Breadcrumbs = CurrentNode.Breadcrumbs;
                bctFilAriane.DataBind();
            }
            else
            {
                bctFilAriane.Visible = false;
            }
        }

        public void InitGroupSelectorWindow()
        {
            MyWindowManager.Windows.Add(GroupSelectorWindow);

            GroupSelectorWindow.OnClientClose = "onGroupSelected";
            GroupSelectorWindow.IconUrl = "/Medianamik/images/Icones/Ico_AjoutPage.gif";
            GroupSelectorWindow.ReloadOnShow = true;
            GroupSelectorWindow.Width = Unit.Pixel(400);
            GroupSelectorWindow.Height = Unit.Pixel(200);

            AddGroup.Attributes.Add("onClick", "GetRadWindowManager().Open(null, 'GroupSelectorWindow');");
            AddGroup.Target = "GroupSelectorWindow";

            InitNavigateUrlToGroupSelectorWindow();
        }

        private void InitNavigateUrlToGroupSelectorWindow()
        {
            AddGroup.NavigateUrl = "/medianamik/contentmanagement/groupselector.aspx";
            if (GroupItems.Count > 0)
            {
                AddGroup.NavigateUrl += string.Format("?without={0}",
                    string.Join(",", GroupItems.Select(x => x.Id.ToString()).ToArray()));
            }
        }

        public static string GetOnGroupSelectedClientScript(string editPageUrl, bool hideTreeview, string parentNodeIdParamName, string typeIdParamName, string returnUrl)
        {
            return String.Concat(" function onGroupSelected(sender, eventArgs) {\n",
                " var argument = eventArgs.get_argument();\n",
                " if (argument && argument.NodeTypeId) {\n",
                " var url = '" + editPageUrl + "?" + typeIdParamName + "=' + argument.NodeTypeId + '&hidetreeview=" + hideTreeview.ToString().ToLower() + "';\n",
                String.IsNullOrEmpty(returnUrl) ? "" : "url += '" + returnUrl + "';\n",
                " if(argument.ParentNodeId) {\n",
                    " url += '&" + parentNodeIdParamName + "=' + argument.ParentNodeId;\n",
                " }\n",
                " location.href = url;",
                " }\n",
                " }\n");
        }

        private void DataBindGroupItems()
        {
            UpdateApprobationLevelsFromIndexes();

            GroupGrid.DataSource = GroupItems;
            GroupGrid.DataBind();

            InitNavigateUrlToGroupSelectorWindow();
        }

        private void InitGrid()
        {
            GroupItems = new List<GroupItem>();
            var approbation = SecurityManager.GetNodeApprobationByNode(CurrentNode);
            if (approbation != null)
            {
                for (int i = 0; i < approbation.GetGroups().Count; i++)
                {
                    var group = approbation.GetGroups()[i];
                    GroupItems.Add(new GroupItem(group.ID, group.Name, i + 1));
                }
                GroupItems = GroupItems;
            }

            GroupGrid.DataSource = GroupItems;

            InitNavigateUrlToGroupSelectorWindow();
        }

        private void UpdateApprobationLevelsFromIndexes()
        {
            for(int i = 0; i < GroupItems.Count; i++)
            {
                GroupItems[i].Index = i + 1;
            }
            GroupItems = GroupItems;
        }

        #endregion

        [Serializable]
        protected class GroupItem
        {
            private readonly Guid _id;
            private readonly string _name;
            private int _index;

            public GroupItem(Guid id, string name, int index)
            {
                _id = id;
                _name = name;
                _index = index;
            }

            public int Index
            {
                get { return _index; }
                set { _index = value; }
            }

            public Guid Id
            {
                get { return _id; }
            }

            public string Name
            {
                get { return _name; }
            }
        }
    }
}
